/*-------------------------------------------------------------------------
 *
 * pg_bswap.h
 *	  字节交换。
 *
 * 反转 16、32 和 64 位无符号整数的字节顺序的宏。
 * 例如，0xAABBCCDD 变为 0xDDCCBBAA。这些仅仅是编译器提供的内置函数的包装。
 *
 * 请注意，所有这些函数接受无符号整数作为参数并返回相同的值。
 * 在使用这些包装宏与有符号整数时请小心。
 *
 * Copyright (c) 2015-2022, PostgreSQL Global Development Group
 *
 * src/include/port/pg_bswap.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef PG_BSWAP_H
#define PG_BSWAP_H


/*
 * 在所有支持的版本中，msvc 在 stdlib.h 提供 _byteswap_* 函数，
 * 该文件已被 c.h 包含。
 */


/* uint16 pg_bswap16(uint16) 的实现 */
#if defined(HAVE__BUILTIN_BSWAP16)

#define pg_bswap16(x) __builtin_bswap16(x)

#elif defined(_MSC_VER)

#define pg_bswap16(x) _byteswap_ushort(x)

#else

static inline uint16
pg_bswap16(uint16 x)
{
	return
		((x << 8) & 0xff00) |
		((x >> 8) & 0x00ff);
}

#endif							/* HAVE__BUILTIN_BSWAP16 */


/* uint32 pg_bswap32(uint32) 的实现 */
#if defined(HAVE__BUILTIN_BSWAP32)

#define pg_bswap32(x) __builtin_bswap32(x)

#elif defined(_MSC_VER)

#define pg_bswap32(x) _byteswap_ulong(x)

#else

static inline uint32
pg_bswap32(uint32 x)
{
	return
		((x << 24) & 0xff000000) |
		((x << 8) & 0x00ff0000) |
		((x >> 8) & 0x0000ff00) |
		((x >> 24) & 0x000000ff);
}

#endif							/* HAVE__BUILTIN_BSWAP32 */


/* uint64 pg_bswap64(uint64) 的实现 */
#if defined(HAVE__BUILTIN_BSWAP64)

#define pg_bswap64(x) __builtin_bswap64(x)


#elif defined(_MSC_VER)

#define pg_bswap64(x) _byteswap_uint64(x)

#else

static inline uint64
pg_bswap64(uint64 x)
{
	return
		((x << 56) & UINT64CONST(0xff00000000000000)) |
		((x << 40) & UINT64CONST(0x00ff000000000000)) |
		((x << 24) & UINT64CONST(0x0000ff0000000000)) |
		((x << 8) & UINT64CONST(0x000000ff00000000)) |
		((x >> 8) & UINT64CONST(0x00000000ff000000)) |
		((x >> 24) & UINT64CONST(0x0000000000ff0000)) |
		((x >> 40) & UINT64CONST(0x000000000000ff00)) |
		((x >> 56) & UINT64CONST(0x00000000000000ff));
}
#endif							/* HAVE__BUILTIN_BSWAP64 */


/*
 * ntohs、ntohl、htons、htonl 的可移植且快速的等效项，
 * 另外扩展到 64 位。
 */
#ifdef WORDS_BIGENDIAN

#define pg_hton16(x)		(x)
#define pg_hton32(x)		(x)
#define pg_hton64(x)		(x)

#define pg_ntoh16(x)		(x)
#define pg_ntoh32(x)		(x)
#define pg_ntoh64(x)		(x)

#else

#define pg_hton16(x)		pg_bswap16(x)
#define pg_hton32(x)		pg_bswap32(x)
#define pg_hton64(x)		pg_bswap64(x)

#define pg_ntoh16(x)		pg_bswap16(x)
#define pg_ntoh32(x)		pg_bswap32(x)
#define pg_ntoh64(x)		pg_bswap64(x)

#endif							/* WORDS_BIGENDIAN */


/*
 * 将 Datum 的字节从大端顺序重排为本地字节顺序。
 * 在大端机器上，这完全没有任何效果。注意，C 类型 Datum 在所有平台上都是无符号整数类型。
 *
 * DatumBigEndianToNative() 宏的一个可能应用是使按位比较更便宜。
 * 通过宏转换的 Datum 的简单 3 步比较（基于本地的无符号比较）将返回与相应原始 Datum 的 memcmp() 相同的结果，
 * 但可能更便宜。在大端系统上，这样做一般是安全的，而不需要事先进行任何特殊转换。
 *
 * 如果 SIZEOF_DATUM 未定义，则表示没有包含 postgres.h，这些宏大概不应该被使用，因此我们不定义任何内容。
 * 注意，在这种情况下，SIZEOF_DATUM == 8 的确会计算为 0 == 8，这可能导致选择错误的实现并产生混淆的错误，
 * 所以不定义任何内容是最安全的。
 */
#ifdef SIZEOF_DATUM
#ifdef WORDS_BIGENDIAN
#define		DatumBigEndianToNative(x)	(x)
#else							/* !WORDS_BIGENDIAN */
#if SIZEOF_DATUM == 8
#define		DatumBigEndianToNative(x)	pg_bswap64(x)
#else							/* SIZEOF_DATUM != 8 */
#define		DatumBigEndianToNative(x)	pg_bswap32(x)
#endif							/* SIZEOF_DATUM == 8 */
#endif							/* WORDS_BIGENDIAN */
#endif							/* SIZEOF_DATUM */

#endif							/* PG_BSWAP_H */
